﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ComponentModel;

namespace WebPALTT.Lib
{
    /// <summary>
    /// A Variable action, which creates a class variable in the script code.
    /// </summary>
    [Serializable]
    public class ActionItem_Variable : ScriptItem
    {
        /// <summary>
        /// Static method containing the CustomType of this action for comparison.
        /// </summary>
        public static string Type { get { return "Variable"; } }
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public override string CustomType { get { return ActionItem_Variable.Type; } }        
        [CategoryAttribute("Action Properties"), ReadOnlyAttribute(true)]
        public override System.Drawing.Image Icon { get { return global::WebPALTT.Lib.Icons.script_code_red; } }
        
        public override bool HasChildren { get { return false; } }
        public override bool CanAddChildren { get { return false; } }
        public override ActionItemCollection Children { get { return null; } }
        public override string[] DataHeaders { get { return new string[] { }; } }
        public override string[] DataHeaders_Save { get { return new string[] { }; } }
        public override ExecutionStatus ExecutionStatus { get { return base.mExecutionStatus; } }
        
        public override string VisibleCode
        {
            get
            {
                return "private " + (IsStatic ? "static " : "") +
                    VarType + " " + Name + (String.IsNullOrEmpty(Value) ? "" : " = " +
                    (Value)) + ";";
            }
            set { throw new InvalidOperationException("Unable to write to this code."); }
        }
        
        public override string ScriptCode
        {
            get
            {
                return "private " + (IsStatic ? "static " : "") + VarType + " @" + Name +
                        (String.IsNullOrEmpty(Value) ? ";" : " = " + Value + ";") + "\r\n";
            }
        }

        public override bool IsCodeEditable { get { return false; } }

        string mType;
        bool mStatic = false;
        string mValue = null;

        /// <summary>
        /// Gets or sets the type of the variable to create.
        /// NB: While any object type that can created from a script action in the same scenario can be used, its recomended to only use primitive types.
        /// </summary>
        [DescriptionAttribute("The type of the variable.")]
        public string VarType { get { return mType; } set { mType = value; } }
        /// <summary>
        /// Gets or sets if the variable is a static variable.
        /// </summary>
        [DescriptionAttribute("Indicates whether the variable is static.")]
        public bool IsStatic { get { return mStatic; } set { mStatic = value; } }
        /// <summary>
        /// Gets or sets the intial value of the variable.
        /// </summary>
        [DescriptionAttribute("The value of the variable as it will appear in the code. NB: Quote marks are required for strings.")]
        public string Value { get { return mValue; } set { mValue = value; } }

        public ActionItem_Variable() : this("") { }

        public ActionItem_Variable(string name) : this(name, "string", false, null) { }

        public ActionItem_Variable(string name, string type, bool isStatic, string value)
            : base(name)
        {
            mType = type;
            mStatic = isStatic;
            mValue = value;
        }

        public ActionItem_Variable(SerializationInfo info, StreamingContext ctxt)
            : base(info, ctxt)
        {
            mType = (string)info.GetValue("Type", typeof(string));
            mStatic = (bool)info.GetValue("Static", typeof(bool));
            mValue = (string)info.GetValue("Value", typeof(string));
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            base.GetObjectData(info, ctxt);
            info.AddValue("Type", mType);
            info.AddValue("Static", mStatic);
            info.AddValue("Value", mValue);
        }

        public override ActionItem FindChild(Guid key) { return null; }
        public override ActionItem[] FindChildren(Guid key) { return null; }        

        public override string[] Validate()
        {
            List<string> errors = new List<string> { };
            if (Name.Equals("Then") || Name.Equals("Else") || Name.Equals("Actions") || Name.Equals("Then"))
                errors.Add("Error: action[" + Name + "(" + ActionType + ")] is using a reserverd name.");

            if (Name.IndexOfAny(new char[] { ' ', '!', '@', '#', '$', '%', '^', '&', '*', '\'', '\"', 
                '(', ')', '[', ']', '{', '}', ';', ':', '.', ',', '\\', '/' }) > -1)
                errors.Add("Error: action[" + Name + "(" + ActionType + ")].Name contains invalid characters.");

            return errors.ToArray();
        }

        public override Dictionary<string, object> Execute(Scenario scenario, ScenarioResults resultScene, Type scriptType, object scriptObj) 
        {
            base.mExecutionStatus = Lib.ExecutionStatus.Complete;
            return new Dictionary<string, object>();
        }
    }    
}
